package request

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"net/url"
	"strings"
)

const (
	contentTypeJson           = "application/json"
	contentTypeFormURLEncoded = "application/x-www-form-urlencoded"
)

type Request struct {
	BaseURL string
	Client  *http.Client
}

func NewRequest(baseURL string) *Request {
	return &Request{
		BaseURL: baseURL,
		Client:  http.DefaultClient,
	}
}

func (r *Request) Get(url string, params *url.Values, headers map[string]string, cookies map[string]string) (resp *http.Response, err error) {
	url = fmt.Sprintf("%s%s", r.BaseURL, url)
	var req *http.Request
	req, err = http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		return
	}
	if params != nil {
		req.URL.RawQuery = params.Encode()
	}
	if headers != nil {
		for k, v := range headers {
			req.Header.Set(k, v)
		}
	}
	if cookies != nil {
		for k, v := range cookies {
			req.AddCookie(&http.Cookie{
				Name:  k,
				Value: v,
			})
		}
	}
	resp, err = r.Client.Do(req)
	return
}

// body can be made by JSONPayload and FormPayload functions
func (r *Request) Post(url string, params *url.Values, body io.Reader, headers map[string]string, cookies map[string]string) (resp *http.Response, err error) {
	url = fmt.Sprintf("%s%s", r.BaseURL, url)
	var req *http.Request
	req, err = http.NewRequest(http.MethodPost, url, body)
	if err != nil {
		return
	}
	if params != nil {
		req.URL.RawQuery = params.Encode()
	}
	if headers != nil {
		for k, v := range headers {
			req.Header.Set(k, v)
		}
	}
	if cookies != nil {
		for k, v := range cookies {
			req.AddCookie(&http.Cookie{
				Name:  k,
				Value: v,
			})
		}
	}
	resp, err = r.Client.Do(req)
	return
}

func Error(url string, statusCode int, body []byte) error {
	return fmt.Errorf("request %s %d: %s", url, statusCode, string(body))
}

func RandomUA() string {
	userAgentList := []string{
		"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36",
		"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.60",
	}
	return userAgentList[rand.Intn(len(userAgentList))]
}

func JSONPayload(data map[string]interface{}) (payload *bytes.Buffer, contentType string, err error) {
	contentType = contentTypeJson
	payload = &bytes.Buffer{}
	err = json.NewEncoder(payload).Encode(data)
	return
}

func FormPayload(values *url.Values) (payload *strings.Reader, contentType string) {
	contentType = contentTypeFormURLEncoded
	payload = strings.NewReader(values.Encode())
	return
}
